package net.aiion.weave;

import net.aiion.weave.asm.AnnotationVisitor;
import net.aiion.weave.asm.ClassWriter;
import net.aiion.weave.asm.Label;
import net.aiion.weave.asm.MethodVisitor;
import net.aiion.weave.asm.Opcodes;
import net.aiion.weave.asm.Type;

public class ConvertingClassDump implements Opcodes
{

    public static byte[] dump() throws Exception {

        ClassWriter cw = new ClassWriter(0);
        MethodVisitor mv;
        AnnotationVisitor av0;

        cw.visit(V1_7, ACC_PUBLIC + ACC_SUPER, "org/weaveframework/conversions/impl/ConvertingClass", null,
            "java/lang/Object", new String[] {
                "org/weaveframework/conversions/spi/Converter"
            });

        cw.visitSource("ConvertingClass.java", null);

        {
            mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
            mv.visitCode();
            Label l0 = new Label();
            mv.visitLabel(l0);
            mv.visitLineNumber(9, l0);
            mv.visitVarInsn(ALOAD, 0);
            mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V");
            Label l1 = new Label();
            mv.visitLabel(l1);
            mv.visitLineNumber(10, l1);
            mv.visitInsn(RETURN);
            Label l2 = new Label();
            mv.visitLabel(l2);
            mv.visitLocalVariable("this", "Lorg/weaveframework/conversions/impl/ConvertingClass;", null, l0, l2, 0);
            mv.visitMaxs(1, 1);
            mv.visitEnd();
        }
        {
            mv = cw.visitMethod(ACC_PUBLIC, "booleanToString",
                "(Lorg/weaveframework/conversions/spi/ConverterContext;)Z", null, null);
            {
                av0 = mv.visitAnnotation("Lorg/weaveframework/conversions/Converts;", true);
                av0.visit("value", Type.getType("Ljava/lang/String;"));
                av0.visitEnd();
            }
            mv.visitCode();
            Label l0 = new Label();
            mv.visitLabel(l0);
            mv.visitLineNumber(14, l0);
            mv.visitVarInsn(ALOAD, 1);
            mv.visitMethodInsn(INVOKEINTERFACE, "org/weaveframework/conversions/spi/ConverterContext",
                "getSourceValue", "()Ljava/lang/Object;");
            mv.visitTypeInsn(CHECKCAST, "java/lang/String");
            mv.visitMethodInsn(INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Ljava/lang/String;)Ljava/lang/Boolean;");
            mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Boolean", "booleanValue", "()Z");
            mv.visitInsn(IRETURN);
            Label l1 = new Label();
            mv.visitLabel(l1);
            mv.visitLocalVariable("this", "Lorg/weaveframework/conversions/impl/ConvertingClass;", null, l0, l1, 0);
            mv.visitLocalVariable("aConverterContext", "Lorg/weaveframework/conversions/spi/ConverterContext;", null,
                l0, l1, 1);
            mv.visitMaxs(1, 2);
            mv.visitEnd();
        }
        {
            mv = cw.visitMethod(ACC_PUBLIC, "convertValue",
                "(Lorg/weaveframework/conversions/spi/ConverterContext;)Ljava/lang/Object;", null, null);
            mv.visitCode();
            mv.visitLdcInsn(Type.getType("Ljava/lang/String;"));
            mv.visitVarInsn(ALOAD, 1);
            mv.visitMethodInsn(INVOKEINTERFACE, "org/weaveframework/conversions/spi/ConverterContext", "getSourceType",
                "()Ljava/lang/Class;");
            mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Class", "isAssignableFrom", "(Ljava/lang/Class;)Z");
            Label l1 = new Label();
            mv.visitJumpInsn(IFEQ, l1);
            mv.visitFieldInsn(GETSTATIC, "java/lang/Boolean", "TYPE", "Ljava/lang/Class;");
            mv.visitVarInsn(ALOAD, 1);
            mv.visitMethodInsn(INVOKEINTERFACE, "org/weaveframework/conversions/spi/ConverterContext", "getTargetType",
                "()Ljava/lang/Class;");
            mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Class", "isAssignableFrom", "(Ljava/lang/Class;)Z");
            mv.visitJumpInsn(IFEQ, l1);
            mv.visitVarInsn(ALOAD, 0);
            mv.visitVarInsn(ALOAD, 1);
            mv.visitMethodInsn(INVOKEVIRTUAL, "org/weaveframework/conversions/impl/ConvertingClass", "booleanToString",
                "(Lorg/weaveframework/conversions/spi/ConverterContext;)Z");
            mv.visitMethodInsn(INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;");
            mv.visitInsn(ARETURN);
            mv.visitLabel(l1);
            mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
            mv.visitVarInsn(ALOAD, 1);
            mv.visitMethodInsn(INVOKEINTERFACE, "org/weaveframework/conversions/spi/ConverterContext",
                "forwardConversion", "()Ljava/lang/Object;");
            mv.visitInsn(ARETURN);
            mv.visitMaxs(2, 2);
            mv.visitEnd();
        }
        cw.visitEnd();

        return cw.toByteArray();
    }
}
